/**
=blacksmith/math - Math functions

The math module provides a number of mathematical functions.

*/


window.MATH = {}

MATH.ONETHIRD = 1/3

MATH.ONESIXTH = 1/6

MATH.T = [0x15, 0x38, 0x32, 0x2c, 0x0d, 0x13, 0x07, 0x2a]

MATH.A = [0, 0, 0]

MATH.s = 0
MATH.X = 0
MATH.Y = 0
MATH.Z = 0
MATH.u = 0
MATH.v = 0
MATH.w = 0
MATH.i = 0
MATH.j = 0
MATH.k = 0
MATH.hi = 0
MATH.lo = 0
MATH.t = 0
MATH.p = 0
MATH.q = 0
MATH.r = 0
MATH.h = 0
MATH.b1 = 0
MATH.b2 = 0
MATH.b3 = 0
MATH.b4 = 0
MATH.b5 = 0

   
MATH.G = function(a) {
    // Returns the hashed gradient indices of a specified corner
    
    MATH.s = (MATH.A[0] + MATH.A[1] + MATH.A[2]) * MATH.ONESIXTH
    MATH.X = MATH.u - MATH.A[0] + MATH.s
    MATH.Y = MATH.v - MATH.A[1] + MATH.s
    MATH.Z = MATH.w - MATH.A[2] + MATH.s
    MATH.t = 0.6 - MATH.X * MATH.X - MATH.Y * MATH.Y - MATH.Z * MATH.Z
    MATH.p = MATH.i + MATH.A[0]
    MATH.q = MATH.j + MATH.A[1]
    MATH.r = MATH.k + MATH.A[2]
    MATH.h = MATH.T[(MATH.p & 1) << 2 | (MATH.q & 1) << 1 | (MATH.r & 1)] +
        MATH.T[(MATH.q >> 1 & 1) << 2 | (MATH.r >> 1 & 1) << 1 | (MATH.p >> 1 & 1)] +
        MATH.T[(MATH.r >> 2 & 1) << 2 | (MATH.p >> 2 & 1) << 1 | (MATH.q >> 2 & 1)] +
        MATH.T[(MATH.p >> 3 & 1) << 2 | (MATH.q >> 3 & 1) << 1 | (MATH.r >> 3 & 1)] +
        MATH.T[(MATH.q >> 4 & 1) << 2 | (MATH.r >> 4 & 1) << 1 | (MATH.p >> 4 & 1)] +
        MATH.T[(MATH.r >> 5 & 1) << 2 | (MATH.p >> 5 & 1) << 1 | (MATH.q >> 5 & 1)] +
        MATH.T[(MATH.p >> 6 & 1) << 2 | (MATH.q >> 6 & 1) << 1 | (MATH.r >> 6 & 1)] +
        MATH.T[(MATH.q >> 7 & 1) << 2 | (MATH.r >> 7 & 1) << 1 | (MATH.p >> 7 & 1)]
    MATH.A[a]++

    if (MATH.t < 0)
        return 0
    
    MATH.b5 = MATH.h >> 5 & 1
    MATH.b4 = MATH.h >> 4 & 1
    MATH.b3 = MATH.h >> 3 & 1
    MATH.b2 = MATH.h >> 2 & 1
    MATH.b1 = MATH.h & 3

    if (MATH.b1 === 1) {
        MATH.p = MATH.X
        MATH.q = MATH.Y
        MATH.r = MATH.Z
    } else if (MATH.b1 === 2) {
        MATH.p = MATH.Y
        MATH.q = MATH.Z
        MATH.r = MATH.X
    } else {
        MATH.p = MATH.Z
        MATH.q = MATH.X
        MATH.r = MATH.Y
    }

    if (MATH.b5 === MATH.b3)
        MATH.p = -MATH.p
    
    if (MATH.b5 === MATH.b4)
        MATH.q = -MATH.q
    
    if (MATH.b5 !== (MATH.b4^MATH.b3))
        MATH.r = -MATH.r
    
    MATH.t *= MATH.t
    
    return (MATH.t * MATH.t * (MATH.p + ((MATH.b1 === 0) ? MATH.q + MATH.r : (MATH.b2 === 0) ? MATH.q : MATH.r)))

}


MATH.noise = function(x, y, z) {
    /**
     *> MATH.noise(x, y, z)
     *
     * Returns the simplex noise function value between -1.0 and 1.0.
     */
    
    // skew input space to relative coordinate in simplex cell
    MATH.s = (x + y + z) * MATH.ONETHIRD // nice skew factor for 3d
    MATH.i = (x + MATH.s) | 0
    MATH.j = (y + MATH.s) | 0
    MATH.k = (z + MATH.s) | 0
    
    // unskew cell origin back to (x, y, z) space
    MATH.s = (MATH.i + MATH.j + MATH.k) * MATH.ONESIXTH // nice unskew factor for 3d
    MATH.u = x - MATH.i + MATH.s
    MATH.v = y - MATH.j + MATH.s
    MATH.w = z - MATH.k + MATH.s
    
    // for 3d the simplex shape is a slightly irregular tetrahedron
    // determine which simplex we are in
    if (MATH.u < MATH.w) {
        MATH.lo = (MATH.u < MATH.v) ? 0 : 1
        MATH.hi = (MATH.v >= MATH.w) ? 1 : 2
    } else {
        MATH.lo = (MATH.v < MATH.w) ? 1 : 2
        MATH.hi = (MATH.u >= MATH.v) ? 0 : 1
    }
    
    MATH.A[0] = MATH.A[1] = MATH.A[2] = 0
    
    // calculate the contribution from the four corners
    return 8 * (MATH.G(hi) + MATH.G(3 - MATH.hi - MATH.lo) + MATH.G(MATH.lo) + MATH.G(0))
}

